package com.piece.core.jpa.repository;

import com.piece.core.db.util.QueryUtil;
import com.piece.core.framework.constant.ExceptionConstants;
import com.piece.core.framework.exception.ServerException;
import com.piece.core.jpa.support.JpaQuery;
import com.piece.core.framework.support.bootstrap.DataTable;
import com.piece.core.framework.support.bootstrap.Order;
import com.piece.core.framework.support.bootstrap.QueryTable;
import com.piece.core.db.util.SearchFilter;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.framework.util.object.ClassUtil;
import com.piece.core.framework.util.string.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaQuery;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.*;

/**
 * Repository 通用CRUD方法
 */
@Slf4j
public class BaseRepository<T, ID extends Serializable> implements IBaseRepository<T, ID> {

    @PersistenceContext
    private EntityManager entityManager;

    protected Class<T> entityClass;

    /**
     * 每次批量操作数
     */
    private int batchSize = 1000;

    public BaseRepository() {
        // 获取当前对象的泛型父类
        ParameterizedType pType = (ParameterizedType) this.getClass().getGenericSuperclass();
        // 获取类型参数的值，就是泛型参数的个数
        this.entityClass = (Class<T>) pType.getActualTypeArguments()[0];
    }

    public Class<T> getEntityClass() {
        return this.entityClass;
    }

    /**
     * 设置批量操作大小
     */
    protected void setBatchSize(int batchSize) {
        this.batchSize = batchSize;
    }

    /**
     * 插入记录
     */
    @Override
    public T insert(T entity) {
        try {
            this.entityManager.persist(entity);
        } catch (Exception e) {
            log.error("插入{}数据异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
        return entity;
    }

    /**
     * 批量插入
     */
    @Override
    @Transient
    public List<T> batchInsert(List<T> list) {
        if (null == list || list.size() == 0) {
            return list;
        }
        for (int i = 0; i < list.size(); i++) {
            list.set(i, insert(list.get(i)));
            if (i % this.batchSize == 0 || i == (list.size() - 1)) {
                this.entityManager.flush();
                this.entityManager.clear();
            }
        }
        return list;
    }

    /**
     * 更新记录
     */
    @Override
    public void update(T entity) {
        try {
            this.entityManager.persist(this.entityManager.merge(entity));
        } catch (Exception e) {
            log.error("更新{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 批量更新
     */
    @Override
    @Transient
    public void batchUpdate(List<T> list) {
        int i = 0;
        for (T entity : list) {
            this.update(list.get(i));
            if (i % this.batchSize == 0 || i == (list.size() - 1)) {
                this.entityManager.flush();
                this.entityManager.clear();
            }
            i++;
        }
    }

    /**
     * 更新非空属性记录
     */
    @Override
    public void updateNotNull(T entity) {
        try {
            Object[] condition = BeanUtil.getKeyProperties(entity, true);
            if (null == condition || null == condition[0]) {
                return;
            }
            Map<String, Object> property = new HashMap<>();
            property = BeanUtil.beanToMap(entity, property, false);
            Map<String, Object> conditions = new HashMap<>();
            conditions.put(condition[0].toString(), condition[1]);
            updateByProperties(conditions, property);
        } catch (Exception e) {
            log.error("更新{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 根据条件更新
     *
     * @param conditionName  条件属性,格式：1.属性名, 2.Q_属性名_条件
     * @param conditionValue 条件属性值
     * @param propertyName   更新属性名
     * @param propertyValue  更新属性值
     */
    @Override
    public int updateByProperties(String conditionName, Object conditionValue, String propertyName, Object propertyValue) {
        Map<String, Object> condition = new HashMap<>();
        condition.put(conditionName, conditionValue);
        return updateByProperties(condition, propertyName, propertyValue);
    }

    /**
     * 根据条件更新
     *
     * @param condition     条件属性,格式：
     *                      <p>1.{属性名，属性值} 2.{Q_属性名_条件，属性值}</p>
     * @param propertyName  更新属性名
     * @param propertyValue 更新属性值
     */
    @Override
    public int updateByProperties(Map<String, Object> condition, String propertyName, Object propertyValue) {
        Map<String, Object> property = new HashMap<>();
        property.put(propertyName, propertyValue);
        return updateByProperties(condition, property);
    }

    /**
     * 根据条件更新
     *
     * @param conditionName  条件属性名,格式：
     *                       <p>1.属性名 2.Q_属性名_条件</p>
     * @param conditionValue 条件属性值
     * @param property       更新属性
     */
    @Override
    public int updateByProperties(String conditionName, Object conditionValue, Map<String, Object> property) {
        Map<String, Object> condition = new HashMap<>();
        condition.put(conditionName, conditionValue);
        return updateByProperties(condition, property);
    }

    /**
     * 根据条件更新
     *
     * @param condition 条件属性,格式：
     *                  <p>
     *                  1.{属性名，属性值}  2.{Q_属性名_条件，属性值}
     *                  条件：LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、 IN:in
     *                  </p>
     * @param property  更新属性
     */
    @Override
    public int updateByProperties(Map<String, Object> condition, Map<String, Object> property) {
        Query query = null;
        try {
            List<Object> conditionValue = new ArrayList<>();
            String hql = "UPDATE " + this.entityClass.getSimpleName() + " SET ";
            Iterator iterator = property.entrySet().iterator();
            int i = 0;
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                hql += entry.getKey() + " = ?" + i++ + ",";
                conditionValue.add(entry.getValue());
            }
            if (hql.endsWith(",")) {
                hql = hql.substring(0, hql.length() - 1);
            }

            hql = generateCondition(hql, condition, conditionValue, false);
            query = this.entityManager.createQuery(hql);

            i = 0;
            for (Object val : conditionValue) {
                query.setParameter(i++, val);
            }
            return query.executeUpdate();
        } catch (Exception e) {
            log.error("更新{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 删除记录
     */
    @Override
    public void delete(T entity) {
        try {
            this.entityManager.remove(this.entityManager.merge(entity));
        } catch (Exception e) {
            log.error("删除{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 批量删除
     */
    @Override
    @Transient
    public void batchDelete(List<T> list) {
        int i = 0;
        for (T object : list) {
            delete(object);
            if (i % this.batchSize == 0 || i == (list.size() - 1)) {
                this.entityManager.flush();
                this.entityManager.clear();
            }
            i++;
        }
    }

    /**
     * 删除记录
     */
    @Override
    public void delete(Serializable id) {
        try {
            this.entityManager.remove(findById(id));
        } catch (Exception e) {
            log.error("删除{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 批量删除
     */
    @Override
    public int delete(Serializable[] ids) {
        try {
            String hql = "DELETE FROM " + this.entityClass.getSimpleName() + " WHERE "
                    + BeanUtil.getKeyName(this.entityClass, true) + " in(";

            for (int i = 0; i < ids.length; i++) {
                hql += "?" + i + ",";
            }
            if (hql.endsWith(",")) {
                hql = hql.substring(0, hql.length() - 1);
            }
            hql += ") ";
            Query query = this.entityManager.createQuery(hql);
            for (int i = 0; i < ids.length; i++) {
                query.setParameter(i, ids[i]);
            }
            return query.executeUpdate();
        } catch (Exception e) {
            log.error("删除{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 根据条件删除
     *
     * @param propName  条件属性,格式：1.属性名 2.Q_属性名_条件
     * @param propValue 属性值
     */
    @Override
    public int deleteByProperties(String propName, Object propValue) {
        if (StringUtil.isEmpty(propName)) {
            throw new ServerException(ExceptionConstants.DELETE_NO_LIMIT, this.entityClass.getSimpleName());
        }
        Map<String, Object> condition = new HashMap<>();
        condition.put(propName, propValue);
        return deleteByProperties(condition);
    }

    /**
     * 根据条件删除
     *
     * @param condition 条件属性
     *                  <p>
     *                  1.{属性名，属性值} 2.{Q_属性名_条件，属性值}
     *                  条件格式：LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、 IN:in
     *                  </p>
     */
    @Override
    public int deleteByProperties(Map<String, Object> condition) {
        Query query = null;
        try {
            if (null == condition) {
                throw new ServerException(ExceptionConstants.DELETE_NO_LIMIT, this.entityClass.getSimpleName());
            }
            List<Object> conditionValue = new ArrayList<>();
            String hql = "DELETE FROM " + this.entityClass.getSimpleName() + " ";
            hql = generateCondition(hql, condition, conditionValue, false);
            query = this.entityManager.createQuery(hql);
            int i = 0;
            for (Object val : conditionValue) {
                query.setParameter(i++, val);
            }
            return query.executeUpdate();
        } catch (Exception e) {
            log.error("删除{}异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    /**
     * 生成hql查询条件
     *
     * @param hql            hql语句
     * @param condition      转换条件,Q_字段名称_类别_条件_关联关系<br>
     *                       Q: 固定查询标识<br>
     *                       字段名称:  属性名称<br>
     *                       类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                       条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                       NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                       关联关系: AND、OR，默认为AND
     * @param conditionValue 转换值
     * @param convertColumn  是否转换列名
     */
    protected String generateCondition(String hql, Map<String, Object> condition, List<Object> conditionValue, boolean convertColumn) {
        return generateCondition(hql, null, condition, conditionValue, convertColumn);
    }

    /**
     * 生成hql查询条件
     *
     * @param hql            hql语句
     * @param alias          查询别名
     * @param condition      转换条件,Q_字段名称_类别_条件_关联关系<br>
     *                       Q: 固定查询标识<br>
     *                       字段名称:  属性名称<br>
     *                       类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                       条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                       NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                       关联关系: AND、OR，默认为AND
     * @param conditionValue 转换值
     * @param convertColumn  是否转换列名
     */
    protected String generateCondition(String hql, String alias, Map<String, Object> condition, List<Object> conditionValue, boolean convertColumn) {
        return QueryUtil.generateCondition(hql, alias, this.entityClass, condition, conditionValue, convertColumn);
    }

    /**
     * 根据id查询单条记录
     */
    @Override
    public T findById(Serializable id) {
        return this.entityManager.find(this.entityClass, id);
    }

    /**
     * 根据条件查询单条记录
     *
     * @param condition 查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                  Q: 固定查询标识<br>
     *                  类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                  条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                  NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                  关联关系: AND、OR，默认为AND
     */
    @Override
    public T findOneByCondition(Map<String, Object> condition) {
        Object obj = null;
        try {
            JpaQuery query = generateQuery(condition);
            obj = this.entityManager.createQuery(query.criteriaQuery()).getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
        return (T) obj;
    }

    /**
     * 根据条件查询单条记录
     *
     * @param sql       查询语句
     * @param condition 查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                  Q: 固定查询标识<br>
     *                  类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                  条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                  NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                  关联关系: AND、OR，默认为AND
     */
    @Override
    public T findOneByCondition(String sql, String alias, Map<String, Object> condition) {
        List<Object> conditionValue = new ArrayList<>();
        String hql = generateCondition(sql, alias, condition, conditionValue, true);

        T result = null;
        try {
            Map<String, Object> map = (Map<String, Object>) setParams(hql, conditionValue, false)
                    .unwrap(SQLQuery.class)
                    .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                    .getSingleResult();
            result = BeanUtil.sqlMapToBean(map, this.entityClass);
        } catch (Exception e) {
            log.error("执行查询操作的sql语句异常：{}", e.getMessage());
        }

        return result;
    }

    /**
     * 根据主键查询记录
     */
    @Override
    public List<T> findByKeys(List<Long> keys) {
        JpaQuery query = JpaQuery.forClass(this.entityClass, this.entityManager, null);
        String key = BeanUtil.getKeyName(this.entityClass, true);
        Map<String, Object> searchParams = new HashMap<>();
        searchParams.put("Q_" + key + "_L_IN", keys);
        query.toPredicate(SearchFilter.parse(searchParams));
        return this.entityManager.createQuery(query.criteriaQuery()).getResultList();
    }

    /**
     * 根据条件查询记录
     *
     * @param entity 实体类查询条件
     */
    @Override
    public List<T> findByConditionWithEntity(T entity, List<Order> orders) {
        Map<String, Object> property = new HashMap<>();
        property = BeanUtil.beanToMap(entity, property, false);
        Map<String, Object> conditions = new HashMap<>();

        Iterator iterator = property.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            conditions.put(entry.getKey().toString(), entry.getValue());
        }
        return findByCondition(conditions, orders);
    }

    /**
     * 根据条件查询记录
     *
     * @param propName  格式：1.属性名，2.Q_属性名_类别_条件_关联关系
     *                  Q: 固定查询标识<br>
     *                  类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                  条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                  NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                  关联关系: AND、OR，默认为AND
     * @param propValue 属性值
     */
    @Override
    public List<T> findByCondition(String propName, Object propValue, List<Order> orders) {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put(propName, propValue);
        return findByCondition(condition, orders);
    }

    /**
     * 根据条件查询记录
     *
     * @param condition 查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                  Q: 固定查询标识<br>
     *                  类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                  条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                  NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                  关联关系: AND、OR，默认为AND
     */
    @Override
    public List<T> findByCondition(Map<String, Object> condition, List<Order> orders) {
        JpaQuery query = generateQuery(condition);
        if (orders != null && orders.size() > 0) {
            for (Order order : orders) {
                query.addOrder(order);
            }
        }
        return this.entityManager.createQuery(query.criteriaQuery()).getResultList();
    }

    /**
     * 根据条件查询记录
     *
     * @param sql       查询语句
     * @param condition 查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                  Q: 固定查询标识<br>
     *                  类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                  条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                  NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                  关联关系: AND、OR，默认为AND
     */
    @Override
    public List<T> findByCondition(String sql, String alias, Map<String, Object> condition, List<Order> orders) {
        List<Object> conditionValue = new ArrayList<>();
        String hql = generateCondition(sql, alias, condition, conditionValue, true);

        if (null != orders && orders.size() > 0) {
            String orderBy = " order by ";
            String orderAttr = "";
            for (Order order : orders) {
                orderAttr = order.getAttr();
                hql += orderBy + orderAttr + " " + order.getSort().getType() + ", ";
                orderBy = "";
            }
            hql = hql.substring(0, hql.length() - 2);
        }

        List result = null;
        List list = setParams(hql, conditionValue, false).unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .getResultList();
        try {
            result = BeanUtil.sqlMapToBean(list, this.entityClass);
        } catch (Exception e) {
            log.error("执行查询操作的sql语句异常：{}", e.getMessage());
        }

        return result;
    }

    /**
     * 分页查询
     *
     * @param queryTable 查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                   Q: 固定查询标识<br>
     *                   类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                   条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                   NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                   关联关系: AND、OR，默认为AND
     */
    @Override
    public DataTable<T> findPage(QueryTable queryTable) {
        return findPage(queryTable, null);
    }

    /**
     * 分组分页查询
     *
     * @param queryTable  查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                    Q: 固定查询标识<br>
     *                    类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                    条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                    NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                    关联关系: AND、OR，默认为AND
     * @param targetClass 分组结果类
     */
    @Override
    public DataTable findPage(QueryTable queryTable, Class targetClass) {
        DataTable dt = new DataTable(queryTable);
        if (null == queryTable)
            return dt;
        JpaQuery query = null;
        if (null != targetClass) {
            query = generateQuery(queryTable.getParams(), targetClass);
        } else {
            query = generateQuery(queryTable.getParams());
        }

        // 子查询
        // TODO: 方法待验证
        Class subClass = queryTable.getSubEntity();
        if (null != subClass) {
            // 获取关联主键
            String projection = queryTable.getSubKey();
            Object projectionValue = queryTable.getSubValue();
            JpaQuery subQuery = JpaQuery.forClass(subClass, this.entityManager, null);
            query.setProjection(projectionValue);
            query.addSubQuery(projection, subQuery);
        }

        // 关联查询
        // TODO: 方法待验证
        Class relClass = queryTable.getReleEntity();
        if (null != relClass) {
            // 获取关联主键
            String relKey = queryTable.getReleKey();
            JpaQuery linkQuery = JpaQuery.forClass(relClass, this.entityManager, null);
            query.addLinkQuery(relKey, linkQuery);
        }

        String group = queryTable.getGroup();
        if (StringUtil.isNotEmpty(group)) {
            query.setGroupBy(group);
        }
        int count = query.count().intValue();
        dt.setRecordsTotal(count);
        query.setBuildCriteriaQuery(false);

        List<Order> orders = queryTable.getOrder();
        if (null != orders && orders.size() > 0) {
            for (Order order : orders) {
                query.addOrder(order);
            }
        }
        int start = queryTable.getStart();
        int size = queryTable.getLength();
        List result = null;

        if (size <= 0) {
            result = this.entityManager.createQuery(query.getCriteriaQuery()).getResultList();
        } else {
            result = this.entityManager.createQuery(query.getCriteriaQuery())
                    .setFirstResult(start)
                    .setMaxResults(size)
                    .getResultList();
        }
        dt.setData(result);
        return dt;
    }

    /**
     * 分组查询
     *
     * @param queryTable  查询条件,格式：Q_字段名称_类别_条件_关联关系<br>
     *                    Q: 固定查询标识<br>
     *                    类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                    条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                    NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                    关联关系: AND、OR，默认为AND
     * @param targetClass 分组结果类
     */
    @Override
    public List findByGroup(QueryTable queryTable, Class targetClass) {
        if (null == queryTable || null == targetClass)
            return new ArrayList();
        queryTable.setLength(0);
        DataTable qt = findPage(queryTable, targetClass);
        if (null != qt && null != qt.getData()) {
            return qt.getData();
        }
        return new ArrayList();
    }

    private JpaQuery generateQuery(Map<String, Object> condition) {
        return generateQuery(condition, null);
    }

    /**
     * 生成查询条件
     *
     * @param condition 格式： Q_字段名称_类别_条件_关联关系<br>
     *                  Q: 固定查询标识<br>
     *                  字段名称:  属性名称
     *                  类别:  S:string、 L:long、 DOU:double、 INT:int、 BD:BigDecimal、 FL:float、 SH:short、 D:date<br>
     *                  条件:  LT:<、 GT:>、 EQ:=、 LE:<=、 GE:>=、 LK:like、EMP:empty、 NEMP:not empty、
     *                  NULL:null、 NNULL:not null、IN:in、 NIN:not in、 NEQ:!=<br>
     *                  关联关系: AND、OR，默认为AND
     */
    private JpaQuery generateQuery(Map<String, Object> condition, Class targetClass) {
        JpaQuery query = JpaQuery.forClass(this.entityClass, this.entityManager, targetClass);
        if (null == condition) {
            return query;
        }
        query.toPredicate(SearchFilter.parse(condition));
        return query;
    }

    /**
     * 统计记录
     *
     * @param sql            查询条件sql
     * @param conditionValue 查询条件参数
     * @param isHql          是否hql语句
     */
    @Override
    public Long count(String sql, List<Object> conditionValue, boolean isHql) {
        String temp = "select count(1) from (" + sql + ") as con";
        if (isHql) {
            int index = sql.toUpperCase().trim().indexOf("FROM");
            temp = sql.substring(index + 4);
            temp = "select count(1) from " + temp;
        }
        return ((Number) (setParams(temp, conditionValue, isHql).getResultList().get(0))).longValue();
    }

    protected Query setParams(String sql, List<Object> conditionValue, boolean isHql) {
        Query query = null;
        if (isHql) {
            query = this.entityManager.createQuery(sql);
        } else {
            query = this.entityManager.createNativeQuery(sql);
        }
        if (ClassUtil.isNotEmpty(conditionValue)) {
            for (int i = 0; i < conditionValue.size(); i++) {
                query.setParameter(i, conditionValue.get(i));
            }
        }
        return query;
    }

    /**
     * 统计记录
     *
     * @param sql            查询条件sql
     * @param conditionValue 查询条件参数
     * @param isHql          是否hql语句
     */
    @Override
    public Long count(String sql, Object[] conditionValue, boolean isHql) {
        String temp = "select count(1) from (" + sql + ") as con";
        if (isHql) {
            int index = sql.toUpperCase().trim().indexOf("FROM");
            temp = sql.substring(index + 4);
            temp = "select count(1) from " + temp;
        }
        return ((Number) (setParams(temp, conditionValue, isHql).getResultList().get(0))).longValue();
    }

    protected Query setParams(String sql, Object[] params, boolean isHql) {
        Query query = null;
        if (isHql) {
            query = this.entityManager.createQuery(sql);
        } else {
            query = this.entityManager.createNativeQuery(sql);
        }
        if (ClassUtil.isNotEmpty(params)) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return query;
    }

    /**
     * 根据query查找记录
     *
     * @param query       查询条件
     * @param firstResult 起始行
     * @param maxResults  结束行
     */
    @Override
    public <T extends Serializable> List<T> find(JpaQuery query, int firstResult, int maxResults) {
        List result = this.entityManager.createQuery(query.getCriteriaQuery())
                .setFirstResult(firstResult)
                .setMaxResults(maxResults)
                .getResultList();
        return result;
    }

    /**
     * 根据query查找记录
     *
     * @param query 查询条件
     */
    @Override
    public <T extends Serializable> List<T> find(JpaQuery query) {
        return this.entityManager.createQuery(query.getCriteriaQuery()).getResultList();
    }

    /**
     * 根据hql查找记录
     *
     * @param hql    hql语句
     * @param params 查询参数
     */
    @Override
    public <T extends Serializable> List<T> find(String hql, Object[] params) {
        return setParams(hql, params, true).getResultList();
    }

    /**
     * 根据hql查询指定数据
     *
     * @param hql         hql
     * @param firstResult 起始行
     * @param maxResults  结束行
     * @param params      查询参数
     */
    @Override
    public <T extends Serializable> List<T> find(String hql, int firstResult, int maxResults, Object[] params) {
        List result = setParams(hql, params, true)
                .setFirstResult(firstResult)
                .setMaxResults(maxResults)
                .getResultList();
        return result;
    }

    /**
     * 查询全部记录
     */
    @Override
    public List findAll() {
        CriteriaQuery criteriaQuery = this.entityManager.getCriteriaBuilder().createQuery(this.entityClass);
        criteriaQuery.from(this.entityClass);
        return this.entityManager.createQuery(criteriaQuery).getResultList();
    }

    /**
     * 查询全部记录
     *
     * @param clazz 实体类
     */
    @Override
    public List findAll(Class clazz) {
        CriteriaQuery criteriaQuery = this.entityManager.getCriteriaBuilder().createQuery(clazz);
        criteriaQuery.from(clazz);
        return this.entityManager.createQuery(criteriaQuery).getResultList();
    }

    /**
     * 执行查询操作的sql语句
     */
    @Override
    public <T extends Serializable> List<T> findBySql(String sql, Object[] params) {
        List list = setParams(sql, params, false).unwrap(SQLQuery.class)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .getResultList();
        try {
            return BeanUtil.sqlMapToBean(list, this.entityClass);
        } catch (Exception e) {
            log.error("执行查询操作的sql语句异常：{}", e.getMessage());
            return new ArrayList<T>();
        }
    }

    /**
     * 执行查询操作的sql语句
     *
     * @param sql         sql
     * @param firstResult 起始行
     * @param maxResults  结束行
     */
    @Override
    public <T extends Serializable> List<T> findBySql(String sql, int firstResult, int maxResults, Object[] params) {
        List list = setParams(sql, params, false).unwrap(SQLQuery.class)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .setFirstResult(firstResult)
                .setMaxResults(maxResults)
                .getResultList();
        try {
            return BeanUtil.sqlMapToBean(list, this.entityClass);
        } catch (Exception e) {
            log.error("执行查询操作的sql语句异常：{}", e.getMessage());
            return new ArrayList<T>();
        }
    }

    /**
     * 执行查询操作的sql语句
     */
    @Override
    public List<Map> findBySqlToMap(String sql, Object[] params) {
        return setParams(sql, params, false).unwrap(SQLQuery.class)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .getResultList();
    }

    /**
     * 执行查询操作的sql语句
     */
    @Override
    public List<Map> findBySqlToMap(String sql, Object[] params, int firstResult, int maxResults) {
        return setParams(sql, params, false).unwrap(SQLQuery.class)
                .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .setFirstResult(firstResult)
                .setMaxResults(maxResults)
                .getResultList();
    }

    /**
     * 查询记录
     *
     * @param clazz     要查询的实体类
     * @param condition 查询条件
     */
    @Override
    public List find(Class clazz, String condition) {
        return this.entityManager.createQuery("select t from " + getTableName(clazz) + " as t where " + condition).getResultList();
    }

    /**
     * 执行更新操作的sql语句
     */
    @Override
    public Integer executeSql(String sql) {
        return this.entityManager.createNativeQuery(sql).executeUpdate();
    }

    /**
     * 执行更新操作的sql语句
     */
    @Override
    public Integer executeSql(String sql, Object[] params) {
        return setParams(sql, params, false).executeUpdate();
    }

    /**
     * 执行更新操作的hql语句
     */
    @Override
    public Integer executeHql(String hql) {
        return this.entityManager.createQuery(hql).executeUpdate();
    }

    /**
     * 执行更新操作的hql语句
     */
    @Override
    public Integer executeHql(String hql, Object[] params) {
        return setParams(hql, params, true).executeUpdate();
    }

    /**
     * 根据hql分页查询
     */
    @Override
    public DataTable<T> findPageByHql(QueryTable queryTable) {
        return findPage(queryTable, true);
    }

    /**
     * 根据sql分页查询
     */
    @Override
    public DataTable<T> findPageBySql(QueryTable queryTable) {
        return findPage(queryTable, false);
    }

    protected DataTable<T> findPage(QueryTable queryTable, boolean isHql) {
        String hql = queryTable.getHql();
        String alias = queryTable.getAlias();
        List<Object> conditionValue = new ArrayList<>();
        hql = generateCondition(hql, alias, queryTable.getParams(), conditionValue, !isHql);
        int count = 0;
        count = count(hql, conditionValue, isHql).intValue();

        int start = queryTable.getStart();
        int size = queryTable.getLength();

        List<Order> orders = queryTable.getOrder();
        if (null != orders && orders.size() > 0) {
            String orderBy = " order by ";
            String orderAttr = "";
            for (Order order : orders) {
                orderAttr = order.getAttr();
                if (!isHql) {
                    orderAttr = BeanUtil.getColumnName(this.entityClass, order.getAttr(), false);
                } else {
                    orderAttr = BeanUtil.getColumnName(this.entityClass, order.getAttr(), true);
                }
                hql += orderBy + orderAttr + " " + order.getSort().getType() + ", ";
                orderBy = "";
            }
            hql = hql.substring(0, hql.length() - 2);
        }

        DataTable dt = new DataTable(queryTable);
        dt.setStart(start);
        dt.setLength(size);
        dt.setRecordsTotal(count);
        List result = null;
        List list = setParams(hql, conditionValue, isHql).unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
                .setFirstResult(start)
                .setMaxResults(size)
                .getResultList();
        try {
            result = BeanUtil.sqlMapToBean(list, this.entityClass);
        } catch (Exception e) {
            log.error("执行查询操作的sql语句异常：{}", e.getMessage());
        }
        dt.setData(null == result ? new ArrayList<T>() : result);
        return dt;
    }

    public boolean checkExist(Serializable id) {
        Serializable[] ids = Arrays.asList(id).stream().toArray(Serializable[]::new);
        return checkExist(ids);
    }

    public boolean checkExist(Serializable[] ids) {
        try {
            String hql = "SELECT count(1) FROM " + BeanUtil.getTableName(this.entityClass) + " WHERE "
                    + BeanUtil.getKeyName(this.entityClass) + " in(";

            for (int i = 0; i < ids.length; i++) {
                hql += "?" + i + ",";
            }
            if (hql.endsWith(",")) {
                hql = hql.substring(0, hql.length() - 1);
            }
            hql += ") ";
            Query query = this.entityManager.createNativeQuery(hql);
            for (int i = 0; i < ids.length; i++) {
                query.setParameter(i, ids[i]);
            }
            return ((Number) (query.getResultList().get(0))).longValue() > 0;
        } catch (Exception e) {
            log.error("检查{}是否存在异常：{}", this.entityClass.getSimpleName(), e.getMessage());
            throw new ServerException(e.getMessage());
        }
    }

    @Override
    public void flush() {
        this.entityManager.flush();
    }

    @Override
    public void clear() {
        this.entityManager.clear();
    }

    protected String getTableName(Class tableClass) {
        return BeanUtil.getTableName(tableClass);
    }
}
